﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tools.Framework
{
    public class ImageHelper
    {
        /// <summary>
        /// 图片水印
        /// </summary>
        /// <param name="ImgFile">原图文件地址</param>
        /// <param name="WaterImg">水印图片地址</param>
        /// <param name="sImgPath">水印图片保存地址</param>
        /// <param name="Alpha">水印透明度设置</param>
        /// <param name="iScale">水印图片在原图上的显示比例(水平)</param>
        /// <param name="intDistance">水印图片在原图上的边距确定,以图片的右边和下边为准,当设定的边距超过一定大小后参数会自动失效</param>
        public static bool ImgWater(string ImgFile, string WaterImg, string sImgPath, float Alpha, float iScale, int intDistance)
        {
            try
            {
                //装载图片
                FileStream fs = new FileStream(ImgFile, FileMode.Open);
                BinaryReader br = new BinaryReader(fs);
                byte[] bytes = br.ReadBytes((int)fs.Length);
                br.Close();
                fs.Close();
                MemoryStream ms = new MemoryStream(bytes);

                System.Drawing.Image imgPhoto = System.Drawing.Image.FromStream(ms);
                int imgPhotoWidth = imgPhoto.Width;
                int imgPhotoHeight = imgPhoto.Height;

                System.Drawing.Image imgWatermark = new Bitmap(WaterImg);
                int imgWatermarkWidth = imgWatermark.Width;
                int imgWatermarkHeight = imgWatermark.Height;


                //计算水印图片尺寸
                decimal aScale = Convert.ToDecimal(iScale);
                decimal pScale = 0.05M;
                decimal MinScale = aScale - pScale;
                decimal MaxScale = aScale + pScale;

                //设置比例
                int imgWatermarkWidthNew = Convert.ToInt32(imgPhotoWidth * aScale);
                int imgWatermarkHeightNew = Convert.ToInt32((imgPhotoWidth * aScale / imgWatermarkWidth) * imgWatermarkHeight);


                //将原图画出来
                Bitmap bmPhoto = new Bitmap(imgPhotoWidth, imgPhotoHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                bmPhoto.SetResolution(72, 72);
                Graphics gbmPhoto = Graphics.FromImage(bmPhoto);

                gbmPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
                gbmPhoto.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                gbmPhoto.Clear(Color.White);
                gbmPhoto.DrawImage(imgPhoto, new Rectangle(0, 0, imgPhotoWidth, imgPhotoHeight), 0, 0, imgPhotoWidth, imgPhotoHeight, GraphicsUnit.Pixel);

                Bitmap bmWatermark = new Bitmap(bmPhoto);
                bmWatermark.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

                Graphics gWatermark = Graphics.FromImage(bmWatermark);

                //指定高质量显示水印图片质量
                gWatermark.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
                gWatermark.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                System.Drawing.Imaging.ImageAttributes imageAttributes = new System.Drawing.Imaging.ImageAttributes();

                //设置两种颜色,达到合成效果
                System.Drawing.Imaging.ColorMap colorMap = new System.Drawing.Imaging.ColorMap();
                colorMap.OldColor = Color.FromArgb(255, 0, 255, 0);
                colorMap.NewColor = Color.FromArgb(0, 0, 0, 0);

                System.Drawing.Imaging.ColorMap[] remapTable = { colorMap };

                imageAttributes.SetRemapTable(remapTable, System.Drawing.Imaging.ColorAdjustType.Bitmap);

                //用矩阵设置水印图片透明度
                float[][] colorMatrixElements = { 
               new float[] {1.0f,  0.0f,  0.0f,  0.0f, 0.0f},
               new float[] {0.0f,  1.0f,  0.0f,  0.0f, 0.0f},
               new float[] {0.0f,  0.0f,  1.0f,  0.0f, 0.0f},
               new float[] {0.0f,  0.0f,  0.0f,  Alpha, 0.0f},
               new float[] {0.0f,  0.0f,  0.0f,  0.0f, 1.0f}
            };

                System.Drawing.Imaging.ColorMatrix wmColorMatrix = new System.Drawing.Imaging.ColorMatrix(colorMatrixElements);
                imageAttributes.SetColorMatrix(wmColorMatrix, System.Drawing.Imaging.ColorMatrixFlag.Default, System.Drawing.Imaging.ColorAdjustType.Bitmap);

                //确定水印边距
                int xPos = imgPhotoWidth - imgWatermarkWidthNew;
                int yPos = imgPhotoHeight - imgWatermarkHeightNew;
                int xPosOfWm = 0;
                int yPosOfWm = 0;

                if (xPos > intDistance)
                    xPosOfWm = xPos - intDistance;
                else
                    xPosOfWm = xPos;

                if (yPos > intDistance)
                    yPosOfWm = yPos - intDistance;
                else
                    yPosOfWm = yPos;

                gWatermark.DrawImage(imgWatermark, new Rectangle(xPosOfWm, yPosOfWm, imgWatermarkWidthNew, imgWatermarkHeightNew), 0, 0, imgWatermarkWidth, imgWatermarkHeight, GraphicsUnit.Pixel, imageAttributes);

                imgPhoto = bmWatermark;


                imgPhoto.Save(sImgPath, System.Drawing.Imaging.ImageFormat.Jpeg);

                //销毁对象
                gbmPhoto.Dispose();
                gWatermark.Dispose();

                imgPhoto.Dispose();
                imgWatermark.Dispose();

                return true;
            }
            catch (Exception )
            {
                return false;
            }
        }



        /// <summary>
        /// 文字水印
        /// </summary>
        /// <param name="ImgFile">原图文件地址</param>
        /// <param name="TextFont">水印文字</param>
        /// <param name="sImgPath">文字水印图片保存地址</param>
        /// <param name="Alpha">文字透明度 其数值的范围在0到255</param>
        /// <param name="widthFont">文字块在图片中所占宽度比例</param>
        /// <param name="hScale">高度位置</param>
        public static bool TextWater(string ImgFile, string TextFont, string sImgPath, int Alpha, float widthFont, float hScale)
        {
            try
            {
                FileStream fs = new FileStream(ImgFile, FileMode.Open);
                BinaryReader br = new BinaryReader(fs);
                byte[] bytes = br.ReadBytes((int)fs.Length);
                br.Close();
                fs.Close();
                MemoryStream ms = new MemoryStream(bytes);

                System.Drawing.Image imgPhoto = System.Drawing.Image.FromStream(ms);
                int imgPhotoWidth = imgPhoto.Width;
                int imgPhotoHeight = imgPhoto.Height;

                Bitmap bmPhoto = new Bitmap(imgPhotoWidth, imgPhotoHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                bmPhoto.SetResolution(72, 72);
                Graphics gbmPhoto = Graphics.FromImage(bmPhoto);
                gbmPhoto.Clear(Color.FromName("white"));//gif背景色
                gbmPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
                gbmPhoto.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                gbmPhoto.DrawImage(imgPhoto, new Rectangle(0, 0, imgPhotoWidth, imgPhotoHeight), 0, 0, imgPhotoWidth, imgPhotoHeight, GraphicsUnit.Pixel);

                //建立字体大小的数组,循环找出适合图片的水印字体
                int[] sizes = new int[] { 1000, 800, 700, 650, 600, 560, 540, 500, 450, 400, 380, 360, 340, 320, 300, 280, 260, 240, 220, 200, 180, 160, 140, 120, 100, 80, 72, 64, 48, 32, 28, 26, 24, 20, 28, 16, 14, 12, 10, 8, 6, 4, 2 };
                System.Drawing.Font crFont = null;
                System.Drawing.SizeF crSize = new SizeF();
                for (int i = 0; i < 43; i++)
                {
                    crFont = new Font("arial", sizes[i], FontStyle.Bold);
                    crSize = gbmPhoto.MeasureString(TextFont, crFont);

                    if ((ushort)crSize.Width < (ushort)imgPhotoWidth * widthFont)
                        break;
                }

                //设置水印字体的位置
                int yPixlesFromBottom = (int)(imgPhotoHeight * hScale);
                float yPosFromBottom = ((imgPhotoHeight - yPixlesFromBottom) - (crSize.Height / 2));
                float xCenterOfImg = (imgPhotoWidth * 1 / 2);

                System.Drawing.StringFormat StrFormat = new System.Drawing.StringFormat();
                StrFormat.Alignment = System.Drawing.StringAlignment.Center;

                //画两次制造透明效果
                System.Drawing.SolidBrush semiTransBrush2 = new System.Drawing.SolidBrush(Color.FromArgb(Alpha, 0, 0, 0));
                gbmPhoto.DrawString(TextFont, crFont, semiTransBrush2, new System.Drawing.PointF(xCenterOfImg + 1, yPosFromBottom + 1), StrFormat);

                System.Drawing.SolidBrush semiTransBrush = new System.Drawing.SolidBrush(Color.FromArgb(Alpha, 255, 255, 255));
                gbmPhoto.DrawString(TextFont, crFont, semiTransBrush, new System.Drawing.PointF(xCenterOfImg, yPosFromBottom), StrFormat);

                bmPhoto.Save(sImgPath, System.Drawing.Imaging.ImageFormat.Jpeg);

                gbmPhoto.Dispose();
                imgPhoto.Dispose();
                bmPhoto.Dispose();

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }


        /// <summary>
        /// 缩略图
        /// </summary>
        /// <param name="ImgFile">原图文件地址</param>
        /// <param name="sImgPath">缩略图保存地址</param>
        /// <param name="ResizeWidth">缩略图宽度</param>
        /// <param name="ResizeHeight">缩略图高度</param>
        /// <param name="BgColor">缩略图背景颜色,注意,背景颜色只能指定KnownColor中的值,如white,blue,red,green等</param>
        public static bool ResizeImg(string ImgFile, string sImgPath, int ResizeWidth, int ResizeHeight, string BgColor)
        {
            try
            {
                FileStream fs = new FileStream(ImgFile, FileMode.Open);
                BinaryReader br = new BinaryReader(fs);
                byte[] bytes = br.ReadBytes((int)fs.Length);
                br.Close();
                fs.Close();
                MemoryStream ms = new MemoryStream(bytes);

                System.Drawing.Image imgPhoto = System.Drawing.Image.FromStream(ms);
                int imgPhotoWidth = imgPhoto.Width;
                int imgPhotoHeight = imgPhoto.Height;
                int StartX = 0;
                int StartY = 0;
                int NewWidth = imgPhotoWidth;
                int NewHeight = imgPhotoHeight;

                //计算缩放图片尺寸
                if (NewWidth > ResizeWidth)
                {
                    NewWidth = ResizeWidth;
                    NewHeight = Convert.ToInt32(imgPhotoHeight * Math.Round(Convert.ToDecimal(NewWidth) / Convert.ToDecimal(imgPhotoWidth), 10));
                }

                if (NewHeight > ResizeHeight)
                {
                    NewHeight = ResizeHeight;
                    NewWidth = Convert.ToInt32(imgPhotoWidth * Math.Round(Convert.ToDecimal(NewHeight) / Convert.ToDecimal(imgPhotoHeight), 10));
                }

                StartX = ResizeWidth - NewWidth;
                StartY = ResizeHeight - NewHeight;

                StartX = StartX > 0 ? StartX / 2 : 0;
                StartY = StartY > 0 ? StartY / 2 : 0;

                Bitmap bmPhoto = new Bitmap(ResizeWidth, ResizeHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                bmPhoto.SetResolution(72, 72);
                Graphics gbmPhoto = Graphics.FromImage(bmPhoto);
                gbmPhoto.Clear(Color.FromName(BgColor));
                gbmPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
                gbmPhoto.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                gbmPhoto.DrawImage(imgPhoto, new Rectangle(StartX, StartY, NewWidth, NewHeight), new Rectangle(0, 0, imgPhotoWidth, imgPhotoHeight), GraphicsUnit.Pixel);
                bmPhoto.Save(sImgPath, System.Drawing.Imaging.ImageFormat.Jpeg);

                imgPhoto.Dispose();
                gbmPhoto.Dispose();
                bmPhoto.Dispose();

                return true;
            }
            catch (Exception )
            {
                return false;
            }
        }


        /// <summary>
        /// 图片剪切
        /// </summary>
        /// <param name="ImgFile">原图文件地址</param>
        /// <param name="sImgPath">缩略图保存地址</param>
        /// <param name="PointX">剪切起始点 X坐标</param>
        /// <param name="PointY">剪切起始点 Y坐标</param>
        /// <param name="CutWidth">剪切宽度</param>
        /// <param name="CutHeight">剪切高度</param>
        public static bool CutImg(string ImgFile, string sImgPath, int PointX, int PointY, int CutWidth, int CutHeight)
        {
            try
            {
                FileStream fs = new FileStream(ImgFile, FileMode.Open);
                BinaryReader br = new BinaryReader(fs);
                byte[] bytes = br.ReadBytes((int)fs.Length);
                br.Close();
                fs.Close();
                MemoryStream ms = new MemoryStream(bytes);
                System.Drawing.Image imgPhoto = System.Drawing.Image.FromStream(ms);

                //System.Drawing.Image imgPhoto = System.Drawing.Image.FromFile(ImgFile);
                //此处只能用filestream，用 System.Drawing.Image则会报多过进程访问文件的错误，会锁定文件
                Bitmap bmPhoto = new Bitmap(CutWidth, CutHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                bmPhoto.SetResolution(72, 72);
                Graphics gbmPhoto = Graphics.FromImage(bmPhoto);
                gbmPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
                gbmPhoto.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                gbmPhoto.DrawImage(imgPhoto, new Rectangle(0, 0, CutWidth, CutHeight), new Rectangle(PointX, PointY, CutHeight, CutHeight), GraphicsUnit.Pixel);
                bmPhoto.Save(sImgPath, System.Drawing.Imaging.ImageFormat.Jpeg);

                imgPhoto.Dispose();
                gbmPhoto.Dispose();
                bmPhoto.Dispose();

                return true;
            }
            catch (Exception err)
            {
                return false;
            }
        }



        /// <summary> 
        /// 图片转换成字节流 
        /// </summary> 
        /// <param name="img">要转换的Image对象</param> 
        /// <returns>转换后返回的字节流</returns> 
        public  static byte[] ImgToByt(Image img) 
        { 
            MemoryStream ms = new MemoryStream(); 
            byte[] imagedata = null; 
            img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 
            imagedata = ms.GetBuffer(); 
            return imagedata;             
        } 
        /// <summary> 
        /// 字节流转换成图片 
        /// </summary> 
        /// <param name="byt">要转换的字节流</param> 
        /// <returns>转换得到的Image对象</returns> 
        public static Image BytToImg(byte[] byt) 
        { 
            MemoryStream ms = new MemoryStream(byt); 
            Image img = Image.FromStream(ms); 
            return img; 
        } 
        // 
        /// <summary> 
        /// 根据图片路径返回图片的字节流byte[] 
        /// </summary> 
        /// <param name="imagePath">图片路径</param> 
        /// <returns>返回的字节流</returns> 
        private static byte[] getImageByte(string imagePath) 
        { 
            FileStream files = new FileStream(imagePath, FileMode.Open); 
            byte[] imgByte = new byte[files.Length]; 
            files.Read(imgByte, 0, imgByte.Length); 
            files.Close(); 
            return imgByte; 
        }



        /// <summary>
        /// base64 转为图片
        /// </summary>
        /// <param name="base64string"></param>
        /// <returns></returns>
        public static Bitmap GetImageFromBase64(string base64string)
        {
            byte[] b = Convert.FromBase64String(base64string);
            MemoryStream ms = new MemoryStream(b);
            Bitmap bitmap = new Bitmap(ms);
            return bitmap;
        }

        /// <summary>
        /// 图片转为base64
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns></returns>
        public static string GetBase64FromImage(Bitmap bmp)
        {
            string strbaser64 = "data:image/jpg;base64,";
            try
            {
                MemoryStream ms = new MemoryStream();
                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();
                strbaser64 += Convert.ToBase64String(arr);
            }
            catch (Exception)
            {
                throw new Exception("Something wrong during convert!");
            }
            return strbaser64;
        }

        /// <summary>
        /// 图片转为base64
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns></returns>
        public static string GetBase64FromImage(MemoryStream ms)
        {
            string strbaser64 = "data:image/jpg;base64,";
            try
            {
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();
                strbaser64 += Convert.ToBase64String(arr);
            }
            catch (Exception)
            {
                throw new Exception("Something wrong during convert!");
            }
            return strbaser64;
        }



        #region MyRegion
              /// <summary>
        /// Convert Image to Byte[]
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public static byte[] ImageToBytes(Image image)
        {
            ImageFormat format = image.RawFormat;
            using (MemoryStream ms = new MemoryStream())
            {
                if (format.Equals(ImageFormat.Jpeg))
                {
                    image.Save(ms, ImageFormat.Jpeg);
                }
                else if (format.Equals(ImageFormat.Png))
                {
                    image.Save(ms, ImageFormat.Png);
                }
                else if (format.Equals(ImageFormat.Bmp))
                {
                    image.Save(ms, ImageFormat.Bmp);
                }
                else if (format.Equals(ImageFormat.Gif))
                {
                    image.Save(ms, ImageFormat.Gif);
                }
                else if (format.Equals(ImageFormat.Icon))
                {
                    image.Save(ms, ImageFormat.Icon);
                }
                byte[] buffer = new byte[ms.Length];
                //Image.Save()会改变MemoryStream的Position，需要重新Seek到Begin
                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(buffer, 0, buffer.Length);
                return buffer;
            }
        }

        /// <summary>
        /// Convert Byte[] to Image
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static Image BytesToImage(byte[] buffer)
        {
            MemoryStream ms = new MemoryStream(buffer);
            Image image = System.Drawing.Image.FromStream(ms);
            return image;
        }

        /// <summary>
        /// Convert Byte[] to a picture and Store it in file
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static string CreateImageFromBytes(string fileName, byte[] buffer)
        {
            string file = fileName;
            Image image = BytesToImage(buffer);
            ImageFormat format = image.RawFormat;
            if (format.Equals(ImageFormat.Jpeg))
            {
                file += ".jpeg";
            }
            else if (format.Equals(ImageFormat.Png))
            {
                file += ".png";
            }
            else if (format.Equals(ImageFormat.Bmp))
            {
                file += ".bmp";
            }
            else if (format.Equals(ImageFormat.Gif))
            {
                file += ".gif";
            }
            else if (format.Equals(ImageFormat.Icon))
            {
                file += ".icon";
            }
            System.IO.FileInfo info = new System.IO.FileInfo(file);
            System.IO.Directory.CreateDirectory(info.Directory.FullName);
            File.WriteAllBytes(file, buffer);
            return file;
        }


        public static string CreateImgToBase64(string imagePath)
        {
            Bitmap bmp = (Bitmap)Image.FromFile(imagePath);
            MemoryStream stream = new MemoryStream();
            bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
            stream.Position = 0;
            byte[] data = new byte[stream.Length];
            stream.Read(data, 0, (int)stream.Length);
            stream.Close();

            string base64String = string.Empty;
            try
            {
                base64String = System.Convert.ToBase64String(data, 0, data.Length);
            }
            catch
            {
                throw;
            }

            StreamWriter outFile;

            try
            {
                outFile = new StreamWriter(string.Concat(imagePath, ".txt"), false, Encoding.ASCII);
                outFile.Write(base64String);
                outFile.Close();
            }
            catch
            {
                throw;
            }

            bmp.Dispose();
            return base64String;
        }

        public static void CreateBase64StrToImage(string filePath)
        {
            StreamReader reader =new StreamReader(filePath);
            string str = reader.ReadToEnd();

            byte[] bitmapData = new byte[str.Length];
            bitmapData = Convert.FromBase64String(FixBase64ForImage(str));
            MemoryStream streamBitmap = new MemoryStream(bitmapData);

            Bitmap bitImage = new Bitmap((Bitmap)Image.FromStream(streamBitmap));
            bitImage.Save(filePath.Substring(0, filePath.Length - 4), System.Drawing.Imaging.ImageFormat.Jpeg);
            bitImage.Dispose();
        }

        static string FixBase64ForImage(string image)
        {
            StringBuilder sbText =
                new StringBuilder(image, image.Length);

            sbText.Replace("\r\n", string.Empty);
            sbText.Replace(" ", string.Empty);

            return sbText.ToString();
        }
        #endregion
    }
}
